package com.autumn.config.client;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.retry.annotation.Retryable;

import com.autumn.config.api.CloudConfigService;
import com.autumn.config.api.vo.ServiceProfileInfo;
import com.autumn.config.api.vo.ServiceProfileValue;
import com.autumn.spring.boot.properties.AutumnCloudProperties;
import com.autumn.util.StringUtils;

/**
 * 配置服务属性源定位器
 * 
 * @author 老码农
 *
 *         2018-06-29 18:05:49
 */
@Order(0)
public class ConfigServicePropertySourceLocator implements PropertySourceLocator {

	private static Log logger = LogFactory.getLog(ConfigServicePropertySourceLocator.class);

	private final CloudConfigService configService;
	private final AutumnCloudProperties cloudProperties;

	/**
	 * 
	 */
	public ConfigServicePropertySourceLocator(CloudConfigService configService, AutumnCloudProperties cloudProperties) {
		this.configService = configService;
		this.cloudProperties = cloudProperties;
	}

	/**
	 * 
	 * @param configService
	 * @param cloudProperties
	 * @return
	 *
	 */
	private ServiceProfileInfo getServiceProfile(org.springframework.core.env.Environment environment,
			CloudConfigService service, AutumnCloudProperties.Config properties, String profile) {
		ServiceProfileValue arg = new ServiceProfileValue();
		if (StringUtils.isNullOrBlank(properties.getLabel())) {
			arg.setLabel(AutumnCloudProperties.Config.DEFAULT_LABEL);
		} else {
			arg.setLabel(properties.getLabel());
		}
		arg.setProfile(profile);
		String serviceId = properties.getName();
		if (StringUtils.isNullOrBlank(serviceId)) {
			serviceId = environment.getProperty("spring.application.name");
		}
		if (StringUtils.isNullOrBlank(serviceId)) {
			logger.error("未配置应用名称或在配置中指定配置名称。");
			return null;
		}
		arg.setServiceId(serviceId);
		Exception error = null;
		try {
			ServiceProfileInfo info = service.serviceProfile(arg);
			if (info == null) {
				return null;
			}
			return info;
		} catch (Exception e) {
			error = e;
		}
		if (error != null) {
			logger.error(error.getMessage(), error);
		}
		return null;
	}

	@Retryable(interceptor = "configServerRetryInterceptor")
	@Override
	public PropertySource<?> locate(org.springframework.core.env.Environment environment) {
		AutumnCloudProperties.Config config = this.cloudProperties.getConfig();
		if (!config.isEnable()) {
			logger.debug("未启用配置中心...");
			return null;
		}
		CompositePropertySource composite = new CompositePropertySource("configService");
		String[] profiles = new String[] { "" };
		if (!StringUtils.isNullOrBlank(cloudProperties.getConfig().getProfile())) {
			profiles = org.springframework.util.StringUtils
					.commaDelimitedListToStringArray(cloudProperties.getConfig().getProfile());
		}
		for (String profile : profiles) {
			ServiceProfileInfo info = getServiceProfile(environment, this.configService, config, profile);
			if (info != null) {
				logger.info(String.format("Located environment: name=%s, profiles=%s, label=%s, version=%s, state=%s",
						info.getProfileName(), profile, info.getLabel(),
						info.getVersion() != null ? info.getVersion().toString() : "", ""));
				if (info.getProfileMap() != null) {
					composite.addPropertySource(new MapPropertySource(info.getName(), info.getProfileMap()));
				}
			} else {
				logger.info(String.format("配置中心未发现配置文件: profiles=%s, label=%s", profile, config.getLabel()));
			}
		}
		return composite;
	}

}
